#pragma once

#include <libmodbus/include/modbus.h>

#include <thread>
#include <set>

#include <common/blocking_queue.hpp>
#include "../../config.hpp"

namespace dcs {


    class tcp_slave_t {
        log_handler_t log_handler_;
        std::uint16_t port_ = 0;
        std::int32_t id_ = 0;
        modbus_t* ctx_ = nullptr;
        modbus_mapping_t* buffer_ = nullptr;

        std::unique_ptr<std::jthread> listen_thr_;
        std::unique_ptr<std::jthread> recv_thr_;

        std::mutex socket_mtx_, queue_mtx_;
        int listen_socket_ = 0;
        std::set<int> sockets_;

        using common_param_t = std::vector<float>;
        using buffer_t = std::tuple<
            std::filesystem::path, 
            std::time_t,
            std::uint16_t,
            common_param_t, 
            std::uint64_t,
            std::function<void(const std::filesystem::path&, std::time_t)>
        >;
        std::queue<buffer_t> buffers_;

    public:
        tcp_slave_t(const log_handler_t&);
        ~tcp_slave_t();

        tcp_slave_t(const tcp_slave_t&) = delete;
        tcp_slave_t& operator=(const tcp_slave_t&) = delete;


        bool start(std::uint16_t, std::int32_t, std::uint32_t registers_num);
        void stop();

        void update(const std::filesystem::path &, std::time_t, std::uint16_t, const common_param_t&, const std::uint64_t&, const std::function<void(const std::filesystem::path&, std::time_t)>&);
        bool handle();
    };


}